#!/bin/sh

assert_datasource() {
	[ -n "${_DATASOURCE_NAME}" ] && return
	[ -d "${RESULTS_D}" ] && [ -r "${RESULTS_D}/dsname" ] ||
		{ debug 2 "no datasource found"; return 1; }

	local dsname="" dsmode=""
	{ read dsname < "${RESULTS_D}/dsname"; } >/dev/null 2>&1 ||
		{ debug 1 "failed to read dsname"; return 1; }

	[ -n "$dsname" ] ||
		{ debug 1 "empty datasource name"; return 1; }

	{ read dsmode < "${RESULTS_D}/dsmode"; } >/dev/null 2>&1 ||
		{ debug 1 "failed to read dsmode"; return 1; }

	_DATASOURCE_NAME="$dsname"
	_DATASOURCE_MODE="$dsmode"
	_RET="${dsname}"
}

ds_list_items() {
	set +f;
	local found=0 start="$PWD" items=""
	cd "${RESULTS_D}/data" || return 1
	for item in *; do
		[ -f "$item" ] || continue
		items="${items}${CR}${item}"
		found=$(($found+1))
	done
	items=${items#${CR}}
	[ -n "$items" ] || debug 2 "empty items in $RESULTS_D/data"
	set -f
	cd "$start" || { debug 2 "failed to cd back to $start"; return 1; }
	[ -n "$items" ] && _RET="$items"
}

ds_get_item_path() {
	assert_datasource || return
	local field="$1"
	local fpath="${RESULTS_D}/data/$field"
	if [ ! -f "$fpath" ]; then
		debug 2 "field $field not available for ds '$_DATASOURCE_NAME'";
		return 2;
	fi
	[ -r "$fpath" ] || { debug 2 "cannot read $field. need root?"; return 1; }
	_RET="$fpath"
	return
}

ds_has_item() {
	[ -f "${RESULTS_D}/data/$1" ]
}

ds_get_item() {
	ds_get_item_path "$1" || return
	local fpath="$_RET"
	# file exists and is readable due to above, if read fails, it is due to EOF.
	read _RET < "$fpath" || :
}

ds_cat_item() {
	ds_get_item_path "$1" && cat "$_RET"
}

cirros_version() {
	[ -r /etc/cirros/version ] ||
		{ _RET="unreleased"; return 0; }
	{ read _RET < /etc/cirros/version; } >/dev/null 2>&1
}

cirros_version_available() {
	local na="0.0" af="$DATA_D/cirros_available"
	local url="http://download.cirros-cloud.net/version/released"
	[ -d "$DATA_D" ] || mkdir -p "$DATA_D"

	[ "$1" = "-f" ] && { rm -f "$af"; shift; }
	local block="${1:-0}"

	if [ ! -f "$af" ]; then
		local max=$block
		[ "$max" = "0" ] && max=20

		local agent="cirros/$CIRROS_VERSION ($(uname -m))"
		local curlcmd="curl --location --silent --fail --max-time $max"

		echo "$na" > "$af"
		if [ "${block}" != "0" ]; then
			local out=""
			out=$($curlcmd --user-agent "$agent" "$url") && echo "$out" > "$af"
		else
			sh -c "out=\$($curlcmd --user-agent '$agent' '$url') &&
				echo \"\${out}\" > '$af'" &
		fi
	fi
	{ read _RET < "$af"; } >/dev/null 2>&1
	[ -n "$_RET" ] || _RET="$na"
	return
}

kver_to_num() {
	# turn a kernel version (X.Y.Z or X.Y.Z-*) into a integer
	local kver="$1" maj="" min="" mic="0"
	kver=${kver%%-*}
	maj=${kver%%.*}
	min=${kver#${maj}.}
	min=${min%%.*}
	mic=${kver#${maj}.${min}.}
	[ "$kver" = "$mic" ] && mic=0
	_RET=$(($maj*1000*1000+$min*1000+$mic))
}

kver_cmp() {
	# kver_cmp(a, operator, b)
	# operator is one "-ge", "-gt", "-lt", "-le", "="
	local op="$2" n1="" n2=""
	kver_to_num "$1"
	n1="$_RET"
	kver_to_num "$3"
	n2="$_RET"
	[ $n1 $op $n2 ]
}

. ${CIRROS_SHLIB:=/lib/cirros/shlib} ||
	{ error "failed to read ${CIRROS_SHLIB}" 1>&2; exit 1; }

INTERNAL=false
VERBOSITY=1
CONFIG=/etc/cirros-init/config
DATA_D=/var/lib/cirros/data
STATE_D=/var/lib/cirros/sem
BOOT_STATE_D=/run/cirros/sem
DS_D=/lib/cirros/ds
RESULTS_D=/run/cirros/datasource

cirros_version
CIRROS_VERSION="$_RET"

[ ! -r "$CONFIG" ] || . "$CONFIG" ||
	fail "failed to read $CONFIG"

# remove any trailing /
STATE_D=${STATE_D%/}
BOOT_STATE_D=${BOOT_STATE_D%/}
DS_D=${DS_D%/}
RESULTS_D=${RESULTS_D%/}

# vi: ts=4 noexpandtab syntax=sh
